package com.kj.tms.common.utils.calx.util;


import com.kj.tms.common.utils.NumberUtils;
import com.kj.tms.common.utils.StringUtil;
import com.kj.tms.common.utils.calx.sheet.Comparator;
import com.kj.tms.common.utils.calx.sheet.Sheet;
import com.kj.tms.common.utils.calx.sheet.Time;
import com.kj.tms.common.utils.calx.formula.Math;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ProjectName: ledger
 * @Package: com.hongtu.tms.ledger.calx.factory
 * @ClassName: Parser
 * @Description: [excel公式语法解析器]
 * @Author: [zhuyongjie]
 * @CreateDate: 2018/4/11 15:38
 * @UpdateUser: []
 * @UpdateDate: 2018/4/11 15:38
 * @UpdateRemark: []
 * @Version: 1.0
 * Copyright: 北京宏图天安 Copyright (c) 2018
 */
public class Parser {
    private Map<String,Object> yy = new HashMap<String, Object>();
    //标识符
    private Map<String, Integer> symbols_;
    //标志位
    private Map<Integer, String> terminals_;
    int[][] productions_;
    List<Map<Integer, Object>> table;
    //词法分析器
    private Lexer lexer;

    private Map<Integer,Object> defaultAction;
    //sheet页
    private Sheet sheet;
    private Integer EOF = 1;//解析结束标识

    public Parser(Sheet sheet) {
        this.sheet = sheet;
        //非终结符
        Symbols symbols = new Symbols();
        symbols_ = symbols.getSymbols();
        //终结符
        Terminals terminals = new Terminals();
        terminals_ = terminals.getTerminals();
        //BNF文法启动集
        Productions productions = new Productions();
        productions_ = productions.getProductions();
        Table tables = new Table();
        table = tables.getTable();
        defaultAction = new HashMap<Integer, Object>();
        defaultAction.put(26, new int[]{2, 1});
        this.lexer= new Lexer();
    }

    private void trace() {
    }

    /**
     * @Method      parse
     * @Param		input
     * @Return      java.lang.String
     * @Exception
     * @Description [解析公式]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/20 16:31
     */
    public String parse(String... input) throws Exception {
        //模拟JavaScript栈
        //存放操作标识
//        List<Integer> stack = new ArrayList<Integer>();
        Stack<Integer> stack = new Stack<Integer>();
        //存放解析出的符号
//        List<Object> vstack = new ArrayList<Object>();
        Stack<Object> vstack = new Stack<Object>();
        //解析步骤存放数组
//        List<Map<String,Integer>> lstack = new ArrayList<Map<String,Integer>>();
        Stack<Map<String,Integer>> lstack = new Stack<Map<String,Integer>>();
        Integer yylineno = 0,//单元格所在行
                yyleng = 0,//单元格编码长度
                recovering = 0,//恢复计算标识
                TERROR = 2;//错误标识

        stack.clear();
//        stack.add(0);
        stack.push(0);
        vstack.clear();
        lstack.clear();
        Parser self = this;
        yylineno = 0;
        yyleng = 0;
        recovering = 0;


        List<Map<Integer, Object>> table = this.table;
        String yytext = "";//单元格编码

        String[] args = new String[input.length - 1];
        if (input.length > 1) {
            //数组拷贝，将动态参数后边的复制
            System.arraycopy(input, 1, args, 0, input.length - 1);
        }
        //设置公式
        lexer.setInput(input[0]);
        lexer.setYy(this.yy);
        this.yy.put("lexer",lexer);
        this.yy.put("parser",this);
        if(lexer.getYylloc() == null){
            lexer.setYylloc(new HashMap<String, Integer>());
        }
        Map<String, Integer> yyloc = lexer.getYylloc();
        //lstack.add(yyloc);
        lstack.push(yyloc);

        String ranges = lexer.getRanges();
        //todo:lexer错误捕捉处理

        Integer state;
        Object symbol = null;
        List<Integer> action = new ArrayList<>();
        List<String> expected = new ArrayList<String>();
        Map<String,Object> yyval = new HashMap<>();
        Integer preErrorSymbol = 0;
        Integer len = 0;
        String r = "";
        while (true){
            action.clear();
            state = stack.get(stack.size() - 1);
            if(!StringUtil.isEmptyOrNull(this.defaultAction.get(state))){
                int[] a = (int[])this.defaultAction.get(state);
                for(int i = 0; i < a.length;i ++){
                    action.add(a[i]);
                }//for end
            }else{
                if(StringUtil.isEmptyOrNull(symbol)){
                    try {
                        //词法分析
                        symbol = lex();
                    } catch (Exception e) {
                        throw e;
                    }
                }//if end

                Object obj = table.get(state).get(symbol);
                if(obj instanceof int[]){
                    int[] a = (int[]) obj;
                    for(int i = 0; i < a.length;i ++){
                        action.add(a[i]);
                    }
                }else if(obj instanceof Integer){
                    action.add((int)obj);
                }//if end
            }//if end
            /*errorHandler(table, state, symbol,
                    action, preErrorSymbol,recovering,EOF,TERROR,
                    yylineno,yyleng,stack,vstack,lstack);*/
            errorHandlerStack(table, state, symbol,
                    action, preErrorSymbol,recovering,EOF,TERROR,
                    yylineno,yyleng,stack,vstack,lstack);
            switch (action.get(0)){
                case 1:
                    /*stack.add(StringUtil.toInt(symbol));
                    vstack.add(lexer.getYytext());
                    lstack.add(lexer.getYylloc());
                    stack.add(action.get(1));*/
                    stack.push(StringUtil.toInt(symbol));
                    vstack.push(lexer.getYytext());
                    lstack.push(lexer.getYylloc());
                    stack.push(action.get(1));
                    symbol = null;
                    if(!StringUtil.isEmptyOrNull(preErrorSymbol)){
                        yyleng = lexer.getYyleng();
                        yytext = lexer.getYytext();
                        yylineno = lexer.getYylineno();
                        yyloc = lexer.getYylloc();
                        if(recovering > 0){
                            recovering --;
                        }
                    }else{
                        symbol = preErrorSymbol;
                        preErrorSymbol = null;
                    }//if end
                    break;
                case 2:
                    len = this.productions_[StringUtil.toInt(action.get(1))][1];
                    yyval.put("$",vstack.get(vstack.size() - len));
                    Map<String,Integer> temp = new HashMap<>();
                    temp.put("first_line",lstack.get(lstack.size() - len).get("first_line"));
                    temp.put("last_line",lstack.get(lstack.size() - 1).get("last_line"));
                    temp.put("first_column",lstack.get(lstack.size() - len).get("first_column"));
                    temp.put("last_column",lstack.get(lstack.size() - 1).get("last_column"));
                    yyval.put("_$",temp);

                    r = this.performAction(yyval,yytext,yyleng,
                            yylineno,action.get(1),vstack,lstack);

                    if(!StringUtil.isEmptyOrNull(r)){
                        return r;
                    }
                    if(len != 0){
//                        popStack(len,stack,vstack,lstack);
                        popStackNew(len,stack,vstack,lstack);
                    }
                   /* stack.add(this.productions_[StringUtil.toInt(action.get(1))][0]);
                    vstack.add(yyval.get("$"));
                    lstack.add((Map<String, Integer>) yyval.get("_$"));*/
                    stack.push(this.productions_[StringUtil.toInt(action.get(1))][0]);
                    vstack.push(yyval.get("$"));
                    lstack.push((Map<String, Integer>) yyval.get("_$"));
                    Integer newState = StringUtil.toInt(table.get(stack.get(stack.size() - 2)).get(stack.get(stack.size() - 1)));
//                    stack.add(newState);
                    stack.push(newState);
                    break;
                case 3:
                    return "";
            }//switch en
        }//while end
    }//parse end

    /**
     * @Method      performAction
     * @Param		yyval
     * @Param		yytext
     * @Param		yyleng
     * @Param		yylineno
     * @Param		state
     * @Param		vstack
     * @Param		lstack
     * @Return      java.lang.String
     * @Exception
     * @Description []
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/16 10:58
     */
    private String performAction(Map<String,Object> yyval, String yytext,
                                 Integer yyleng,
                                 Integer yylineno, Integer state,
                                 List<Object> vstack,
                                 List<Map<String, Integer>> lstack)
            throws Exception {

        int len = vstack.size() - 1;
//        System.out.println(state);
        switch (state){
            case 1:
                return StringUtil.toString(vstack.get(len - 1));
            case 2:
                //todo:
                yyval.put("$",this.sheet.getVariable(StringUtil.toString(vstack.get(len))));
                break;
            case 3:
                yyval.put("$",true);
                break;
            case 4:
                yyval.put("$",false);
                break;
            case 5:
                yyval.put("$",null);
                break;
            case 6:
                //12小时制 时间格式
                yyval.put("$", Time.time(vstack.get(len)));
                break;
            case 7:
                //24小时制 时间格式
                yyval.put("$", Time.time(vstack.get(len)));
               break;
            case 8:
                yyval.put("$", StringUtil.toString(vstack.get(len)));
                break;
            case 9:
                int length = StringUtil.toString(vstack.get(len)).length();
                yyval.put("$", StringUtil.toString(vstack.get(len)).substring(1,length - 1));
                break;
            case 10:
                yyval.put("$", StringUtil.toString(vstack.get(len - 2)) + StringUtil.toString(vstack.get(len)));
            break;
            case 11://等于

                yyval.put("$", Comparator.equal(vstack.get(len - 2),vstack.get(len)));
                break;
            case 12:
                Map<String,Object> sumMap = new HashMap<>();
                sumMap.put("1",vstack.get(len - 2));
                sumMap.put("2",vstack.get(len));
                yyval.put("$", FormulaFactory.callFunction("SUM",sumMap,this.sheet));
                break;

            case 13:
                yyval.put("$",vstack.get(len - 1));

                break;
            case 14:
                yyval.put("$",vstack.get(len - 1));

                break;
            case 15:
                //小于等于
                yyval.put("$", Comparator.lessEqual(vstack.get(len - 3),vstack.get(len)));
                break;
            case 16:
                //大于等于
                yyval.put("$", Comparator.greaterEqual(vstack.get(len - 3),vstack.get(len)));
                break;
            case 17:
                //不等于
                yyval.put("$", Comparator.notEqual(vstack.get(len - 3),vstack.get(len)));
                break;
            case 18:
                yyval.put("$",vstack.get(len - 2) != vstack.get(len));
                break;
            case 19:
                //大于
                yyval.put("$", Comparator.greater(vstack.get(len - 2),vstack.get(len)));
                break;
            case 20:
                //小于
                yyval.put("$", Comparator.less(vstack.get(len - 2),vstack.get(len)));
                break;
            case 21:
                //-减法
                yyval.put("$", Math.SUBTRACT(StringUtil.toString(vstack.get(len - 2)), StringUtil.toString(vstack.get(len))));
                break;
            case 22:
                //*乘法

                 yyval.put("$", Math.MULTIPLY(StringUtil.toString(vstack.get(len - 2)), StringUtil.toString(vstack.get(len))));
                break;
            case 23:
                //除法
                 yyval.put("$", Math.DIVIDE(StringUtil.toString(vstack.get(len - 2)), StringUtil.toString(vstack.get(len))));
                break;
            case 24:
                //^幂运算

                 yyval.put("$", Math.POWER(StringUtil.toDouble(vstack.get(len - 2)), StringUtil.toDouble(vstack.get(len))));
                break;
            case 25:
                double i = StringUtil.toDouble(vstack.get(len));
                i = i * -1;
                yyval.put("$",i);
                break;
            case 26:
                 yyval.put("$", StringUtil.toDouble(vstack.get(len)));
                break;
            case 27:
                yyval.put("$", java.lang.Math.E);
                break;

            case 28:
                //激活函数
//                System.out.println(vstack.get(len - 2) + " ; " + vstack.get(len - 1));

                yyval.put("$", FormulaFactory.callFunction(StringUtil.toString(vstack.get(len - 2)),vstack.get(len - 1),this.sheet));
                break;
            case 29:
                //激活函数
                yyval.put("$", FormulaFactory.callFunction(StringUtil.toString(vstack.get(len - 3)),vstack.get(len - 1),this.sheet));
                break;

            case 33:
                //todo:
                yyval.put("$",this.sheet.getCellValue(StringUtil.toString(vstack.get(len))));
                break;
            case 34:
                //A1:B3值
                yyval.put("$", this.sheet.getCellRangeValue(StringUtil.toString(vstack.get(len - 2)), StringUtil.toString(vstack.get(len))));
                break;

            case 35:
                yyval.put("$",this.sheet.getCellValue(StringUtil.toString(vstack.get(len))));
                break;
            case 36:
                //A1:B3值
                yyval.put("$", this.sheet.getCellRangeValue(StringUtil.toString(vstack.get(len - 2)), StringUtil.toString(vstack.get(len))));
                break;
            case 37:
                //todo:表间

                 yyval.put("$","");
                break;
            case 38:
                //todo:表间

            case 39:
                //todo:列范围

                 yyval.put("$","");
                break;
            case 40:
                //todo:表间列范围

                 yyval.put("$","");
                break;
            case 41:
                yyval.put("$",vstack.get(len));
                break;
            case 42:
                Object o = vstack.get(len - 2);
                List<Object> l ;
                if(o instanceof ArrayList){
                    l = (ArrayList)o;
                }else{
                    l = new ArrayList<>();
                    l.add(o);
                }
                l.add(vstack.get(len));
                vstack.set(len - 2,l);
                yyval.put("$",vstack.get(len - 2));
                break;
            case 43:
                o = vstack.get(len - 2);
                if(o instanceof ArrayList){
                    l = (ArrayList)o;
                }else{
                    l = new ArrayList<>();
                    l.add(o);
                }
                l.add(vstack.get(len));
                vstack.set(len - 2,l);
                yyval.put("$",vstack.get(len - 2));
                break;
            case 44:
                List arr = new ArrayList();
                arr.add(vstack.get(len));
                yyval.put("$",arr);
                break;
            case 45:
                if(vstack.get(len - 2) instanceof ArrayList){
                    List a = (ArrayList) vstack.get(len - 2);
                    a.add(vstack.get(len));
                    yyval.put("$",a);
                }else{
                    List a = new ArrayList();
                    a.add(vstack.get(len - 2));
                    a.add(vstack.get(len));
                    yyval.put("$",a);
                }
                break;
            case 46:

                 yyval.put("$",vstack.get(len));
                break;
            case 47:
                yyval.put("$", StringUtil.toString(vstack.get(len - 2))
                        + "."
                        + StringUtil.toString(vstack.get(len)));
                break;
            case 48:
                yyval.put("$", StringUtil.toDouble(vstack.get(len - 1)) * 0.01);
                break;
            case 49:
                 yyval.put("$", StringUtil.toDouble(vstack.get(len - 2))
                         + StringUtil.toDouble(vstack.get(len - 1))
                         + StringUtil.toDouble(vstack.get(len)));
                break;
            case 50:
                yyval.put("$", StringUtil.toDouble(vstack.get(len - 2))
                        + StringUtil.toDouble(vstack.get(len - 1))
                        + StringUtil.toDouble(vstack.get(len)));
                break;
        }//switch end
        return null;
    }//performAction end

    /**
     * @Method      errorHandler
     * @Param		table
     * @Param		state
     * @Param		symbol
     * @Param		action
     * @Param		preErrorSymbol
     * @Return      void
     * @Exception
     * @Description [处理异常捕捉]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/13 14:50
     */
    private void errorHandler(List<Map<Integer, Object>> table,
                              Integer state, Object symbol,
                              List<Integer> action, Integer preErrorSymbol,
                              Integer recovering, Integer EOF, Integer TERROR,
                              Integer yylineno, Integer yyleng, List<Integer> stack,
                              List<Object> vstack,
                              List<Map<String, Integer>> lstack)
            throws Exception {
        List<String> expected;
        String yytext;
        Map<String, Integer> yyloc;//错误处理
        _handle_error:if(StringUtil.isEmptyOrNull(action)
                || action.size() ==0
                || StringUtil.isEmptyOrNull(action.get(0))){

//            System.out.println("处理错误：" + state);
            Integer error_rule_depth = null;
            String errStr = "";


            if(recovering == 0){
                error_rule_depth = locateNearestErrorRecoveryRule(state,stack,TERROR);
                expected = new ArrayList<String>();
                Map<Integer, Object> map = table.get(state);
                //循环
                for(Map.Entry<Integer,Object> entry : map.entrySet()){
                    int key = StringUtil.toInt(entry.getKey());
                    if(!StringUtil.isEmptyOrNull(this.terminals_.get(key))
                            && key > TERROR){
                        expected.add("'" + this.terminals_.get(key) + "'");
                    }
                }//for end

                if(!StringUtil.isEmptyOrNull(this.lexer.showPosition())){
                    errStr = "Parse error on line " + (yylineno + 1)
                            + ":\n" + this.lexer.showPosition()
                            + "\nExpecting " + expected.toString()
                            + ", got '" + this.terminals_.get(symbol)
                            + "\t" + symbol + "'";
                }else{
                    errStr = "Parse error on line "
                            + (yylineno + 1) + ": Unexpected "
                            + (symbol == EOF ? "end of input" : "'"
                            + (this.terminals_.get(symbol) + "\t"
                            + symbol) + "'");
                }//if end

                throw new Exception(errStr);

            }else if(preErrorSymbol != EOF){
                error_rule_depth = locateNearestErrorRecoveryRule(state, stack, state);
            }//if end

            if(recovering == 3){
                if(symbol == EOF || preErrorSymbol == EOF){
                    throw new Exception(errStr + " Parsing halted while starting to recover from another error.");
                }
                yyleng = this.lexer.getYyleng();
                yytext = this.lexer.getYytext();
                yylineno = this.lexer.getYylineno();
                yyloc = this.lexer.getYylloc();
                symbol = lex();

            }//if end
            if(StringUtil.isEmptyOrNull(error_rule_depth)){
                throw new Exception(errStr + "Parsing halted. No suitable error recovery rule available.");
            }

            popStack(error_rule_depth, stack, vstack, lstack);
            preErrorSymbol = symbol == TERROR ? null : StringUtil.toInt(symbol);
            symbol = TERROR;
            state = stack.get(stack.size() - 1);

            Object obj = table.get(state).get(TERROR);
            if(obj instanceof int[]){
                int[] a = (int[]) obj;
                for(int i = 0; i < a.length;i ++){
                    action.add(a[i]);
                }
            }else if(obj instanceof Integer){
                action.add((int)obj);
            }//if end
            recovering = 3;


        }//_handle_error if end
    }//errorHandler end

    /**
     * @Method      errorHandler
     * @Param		table
     * @Param		state
     * @Param		symbol
     * @Param		action
     * @Param		preErrorSymbol
     * @Return      void
     * @Exception
     * @Description [处理异常捕捉]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/13 14:50
     */
    private void errorHandlerStack(List<Map<Integer, Object>> table,
                                   Integer state, Object symbol,
                                   List<Integer> action, Integer preErrorSymbol,
                                   Integer recovering, Integer EOF, Integer TERROR,
                                   Integer yylineno, Integer yyleng, Stack<Integer> stack,
                                   Stack<Object> vstack,
                                   Stack<Map<String, Integer>> lstack)
            throws Exception {
        List<String> expected;
        String yytext;
        Map<String, Integer> yyloc;//错误处理
        _handle_error:if(StringUtil.isEmptyOrNull(action)
                || action.size() ==0
                || StringUtil.isEmptyOrNull(action.get(0))){

//            System.out.println("处理错误：" + state);
            Integer error_rule_depth = null;
            String errStr = "";


            if(recovering == 0){
                error_rule_depth = locateNearestErrorRecoveryRule(state,stack,TERROR);
                expected = new ArrayList<String>();
                Map<Integer, Object> map = table.get(state);
                //循环
                for(Map.Entry<Integer,Object> entry : map.entrySet()){
                    int key = StringUtil.toInt(entry.getKey());
                    if(!StringUtil.isEmptyOrNull(this.terminals_.get(key))
                            && key > TERROR){
                        expected.add("'" + this.terminals_.get(key) + "'");
                    }
                }//for end

                if(!StringUtil.isEmptyOrNull(this.lexer.showPosition())){
                    errStr = "Parse error on line " + (yylineno + 1)
                            + ":\n" + this.lexer.showPosition()
                            + "\nExpecting " + expected.toString()
                            + ", got '" + this.terminals_.get(symbol)
                            + "\t" + symbol + "'";
                }else{
                    errStr = "Parse error on line "
                            + (yylineno + 1) + ": Unexpected "
                            + (symbol == EOF ? "end of input" : "'"
                            + (this.terminals_.get(symbol) + "\t"
                            + symbol) + "'");
                }//if end

                throw new Exception(errStr);

            }else if(preErrorSymbol != EOF){
                error_rule_depth = locateNearestErrorRecoveryRule(state, stack, state);
            }//if end

            if(recovering == 3){
                if(symbol == EOF || preErrorSymbol == EOF){
                    throw new Exception(errStr + " Parsing halted while starting to recover from another error.");
                }
                yyleng = this.lexer.getYyleng();
                yytext = this.lexer.getYytext();
                yylineno = this.lexer.getYylineno();
                yyloc = this.lexer.getYylloc();
                symbol = lex();

            }//if end
            if(StringUtil.isEmptyOrNull(error_rule_depth)){
                throw new Exception(errStr + "Parsing halted. No suitable error recovery rule available.");
            }

            popStackNew(error_rule_depth, stack, vstack, lstack);
            preErrorSymbol = symbol == TERROR ? null : StringUtil.toInt(symbol);
            symbol = TERROR;
            state = stack.get(stack.size() - 1);

            Object obj = table.get(state).get(TERROR);
            if(obj instanceof int[]){
                int[] a = (int[]) obj;
                for(int i = 0; i < a.length;i ++){
                    action.add(a[i]);
                }
            }else if(obj instanceof Integer){
                action.add((int)obj);
            }//if end
            recovering = 3;


        }//_handle_error if end
    }//errorHandlerStack end

    /**
     * @Method      locateNearestErrorRecoveryRule
     * @Param		state
     * @Return      int
     * @Exception
     * @Description [查找最近的恢复规则]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/13 11:55
     */
    private Integer locateNearestErrorRecoveryRule(Integer state, List<Integer> stack, Integer TERROR) {
        int stack_probe = stack.size() - 1;
        int depth  =0;
        for(;;){
            if(!StringUtil.isEmptyOrNull(this.table.get(state).get(TERROR))){
                return depth;
            }
            if(state == 0 || stack_probe < 2){
                return null;
            }
            stack_probe -= 2;
            state = stack.get(stack_probe);
            ++depth;
        }//for end
    }//locateNearestErrorRecoveryRule end

    /**
     * @Method      lex
     * @Param
     * @Return      java.lang.Object
     * @Exception
     * @Description [词法分析]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/12 10:00
     */
    private Object lex() throws Exception {
        Object token = "";
        Object lex = this.lexer.lex();
        token = !StringUtil.isEmptyOrNull(lex) ? lex : this.EOF;
        if(!NumberUtils.isRealNumber(token.toString())){
            token = this.symbols_.get(token) != null ? this.symbols_.get(token) : token;
        }//if end
        return token;
    }//lex() end

    /**
     * @Method      isNumeric
     * @Param		str
     * @Return      boolean
     * @Exception
     * @Description [判断字符串是否是数字]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/12 9:56
     */
    public boolean isNumeric(String str){
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if( !isNum.matches() ){
            return false;
        }
        return true;
    }//isNumeric end


    /**
     * @Method      popStack
     * @Param		n
     * @Return      void
     * @Exception
     * @Description [List模拟出栈操作]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/12 9:18
     */
    private void popStack(Integer n, List<Integer> stack,
                          List<Object> vstack,
                          List<Map<String, Integer>> lstack){
        removeListStack(2 * n,stack);
        removeListStack(n,vstack);
        removeListStack(n,lstack);
    }//popStack end

    /**
     * @Method      popStackNew
     * @Param		n
     * @Param		stack
     * @Param		vstack
     * @Param		lstack
     * @Return      void
     * @Exception
     * @Description [出栈操作]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/5/7 9:43
     */
    private void popStackNew(Integer n, Stack<Integer> stack,
                             Stack<Object> vstack, Stack<Map<String,Integer>> lstack){
       stack.setSize(stack.size() - 2 * n);
       vstack.setSize(vstack.size() - n);
       lstack.setSize(lstack.size() - n);
    }//popStackNew end

    /**
     * @Method      removeListStack
     * @Param		n 出栈元素数量
     * @Param		list 模拟栈的List
     * @Return      void
     * @Exception
     * @Description [使用List模拟出栈操作]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/12 9:33
     */
    private void removeListStack(Integer n, List<?> list){
        if(list != null){
            if(list.size() > n){
                for(int i = 0; i < n;i ++){
                    list.remove(list.size() - 1);
                }
            }else{
                //清空栈
                list.clear();
            }//if end
        }//if end
    }//if end

    public static void main(String[] args) {
        Parser parser = new Parser(new Sheet());

        try {
//            String parse = parser.parse("SUM(A1:A2)");
//            String parse = parser.parse("if(2>3,3,4)");
//            String parse = parser.parse("abs(-1)");

//            String parse = parser.parse("MOD(4,-2)");
//            String parse = parser.parse("power(3,2)");

//            String parse = parser.parse("round(sum(a1:a2),2)");
//            String parse = parser.parse("ROUNDDOWN(3.1415926,4)");
//            String parse = parser.parse("ROUNDUP(3.1415926,4)");

//            String parse = parser.parse("not(2)");
//            String parse = parser.parse("or(1<=2,2<=3,4<=3,4<=5)");
//            String parse = parser.parse("or(2<=1,false,1)");
//            String parse = parser.parse("true()");

//            String parse = parser.parse("and(1<=2,2<=3,4<=3,4<=5)");
//            String parse = parser.parse("average(1,2,3,4)");
//            String parse = parser.parse("count(1,2,3,4)");
//            String parse = parser.parse("sumif(a1:a2,'>0',a1:a2)");
//            String parse = parser.parse("'12:21:21'<='11:21:12'");

//            String parse = parser.parse("8:21:21am");

            String parse = parser.parse("SUMIF(AMTA4:AMTB4,>10,AMTA4:AMTB4)");



            System.out.println("result : " + parse);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
